package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishDto;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author ：sean
 * @date ：Created in 2022/5/20
 * @description ：菜品控制器
 * @version: 1.0
 */
@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {

	@Autowired
	private DishService dishService;

	@Autowired
	private CategoryService categoryService;

	@PostMapping
	// 参数怎么写，写什么？
	public R<String> save(@RequestBody DishDto dishDto){
		log.info("[新增菜品] dish:{}",dishDto);
		// 问题的是，请求的数据，并没有完全接收到？
		// 现在控制器已经拿到数据，现在需要干嘛？
		// 分开存（数据保护菜品基本信息和菜品的口味信息）
		//  dishService 不能同时保存菜品基本信息和菜品的口味信息
		// 结论：需要自己扩展业务方法，完成保存
		dishService.saveWithFlavor(dishDto);

		// 保存后，我们需要更新redis,删除指定的一个
		String key ="dish_"+dishDto.getCategoryId()+"_1";
		redisTemplate.delete(key);
		return R.success("保存成功");
	}
	// 写方法：方法名，参数列表，返回值

	/**
	 * 分页获取菜品列表
	 * @param page 当前页码
	 * @param pageSize 每页记录数
	 * @param name 按菜品名字模拟条件
	 * @return
	 */
	@GetMapping("/page")
	public R<Page> page(int page,int pageSize,String name){
		log.info("[菜品分页],{},{},{}",page,pageSize,name);
		// 分页获取，套路很固定
		// 构建Page对象
		Page pageInfo = new Page(page,pageSize);
		// 根据条件查询,按名字模糊查询，按更新日期倒叙排列
		LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
		dishLambdaQueryWrapper.like(StringUtils.isNotEmpty(name),Dish::getName,name);
		dishLambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);
		// 返回page对象
		dishService.page(pageInfo,dishLambdaQueryWrapper);
		// pageInfo可以返回了
		// 现在页码展示是什么问题？不能线上分类的名称，我们也不可以直接在实体类中加入一个属性
		// 结论：返回的记录集应该用DishDto替换，因为DishDto在里面加入分类名称
		// 思路：数据已经在pageInfo的records里面了（Dish）换成DishDto
		// 构建应该Page<DishDto>
		Page<DishDto> dishDtoPage  = new Page<>(); // 这个对象啥也没有，把pageInfo复制进来
		// 复制的过程，可以忽略掉不需要的或目前没必要的属性
		// pageInfo（page,pageSize ,records,total)
		BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");
		// 我们需要单独把records里面的Dish换成DishDto
		List<Dish> records = pageInfo.getRecords();
		// 遍历这个结果集，把每条记录，换成DishDto,然后把dishDto存入应该新的列表中
		List<DishDto> dishDtoList = new ArrayList<>();
		//for(Dish dish:records){
		//	DishDto dishDto = new DishDto();
		//	// 把dish对象的数据复制dishDto
		//	BeanUtils.copyProperties(dish,dishDto);
		//	// 固定写死，先测试，后获取真实的分类名称
		//	// 当前菜品的分类名称，应该如何获取？
		//	// 结论：根据当前菜品分类的ID，通过分类业务对象，来获取分类对象。
		//	Category category = categoryService.getById(dish.getCategoryId());
		//	dishDto.setCategoryName(category.getName());
		//	dishDtoList.add(dishDto);
		//}
		// lambda语法
		//records.stream().map((itemOne)->{
		//	DishDto dishDto = new DishDto();
		//	// 把dish对象的数据复制dishDto
		//	BeanUtils.copyProperties(itemOne,dishDto);
		//	// 固定写死，先测试，后获取真实的分类名称
		//	// 当前菜品的分类名称，应该如何获取？
		//	// 结论：根据当前菜品分类的ID，通过分类业务对象，来获取分类对象。
		//	Category category = categoryService.getById(itemOne.getCategoryId());
		//	if (category !=null){
		//		dishDto.setCategoryName(category.getName());
		//	}
		//	return itemOne;
		//});
		records.stream().map((item)->{
			DishDto dishDto = new DishDto();
			// 把dish对象的数据复制dishDto
			BeanUtils.copyProperties(item,dishDto);
			Category category = categoryService.getById(item.getCategoryId());
			if(category != null){
				dishDto.setCategoryName(category.getName());
			}
			dishDtoList.add(dishDto);
			return item;
		}).collect(Collectors.toList());

		// 把新的结果集复制给Page对象
		dishDtoPage.setRecords(dishDtoList);
		return R.success(dishDtoPage);
	}

	//方法三要素：方法名，参数，返回类型
	// /dish/1527550406303969282
	@GetMapping("/{id}")
	public R<DishDto> get(@PathVariable Long id){
		log.info("[根据ID，获取菜品信息],id:{}",id);
		// 如果dishService没有对应的业务，直接返回DishDto,我们需以扩展业务方法
		DishDto dishDto = dishService.getByIdWithFlavor(id);
		return R.success(dishDto);
	}

	// 方法三要素：方法名，参数，返回值
	@PutMapping
	public R<String> update(@RequestBody DishDto dishDto){
		log.info("[菜品修改],dto:{}",dishDto);
		// 调用Service的业务方法，完成业务
		// dishService.updateById(dishDto);// 只是更新菜品的基本信息
		dishService.updateWithFlavor(dishDto);
		// 更新菜品后，全部删除与列表有的key,通配符
		//String keys ="dish_*";
		// redisTemplate相当于redis客户端
		// keys搜索，匹配的key，返回的列表
		Set keys = redisTemplate.keys("dish_*");
		// 如果提供的是key结合，按集合替换提供数据key删除
		redisTemplate.delete(keys);

		return R.success("更新成功");
	}
	// http://localhost:8080/dish/list?categoryId=1397844263642378242

	/**
	 * 根据分类ID，获取菜品下的列表
	 * @param categoryId
	 * @return
	 */
	//@GetMapping("/list")
	//public R<List<Dish>> list(Long categoryId){
	//	log.info("[菜品管理-获取菜品列表],categoryId:{}",categoryId);
	//	List<Dish> dishList = new ArrayList<>();
	//	// 调用业务，获取真正的列表
	//	LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
	//	dishLambdaQueryWrapper.eq(categoryId!=null,Dish::getCategoryId,categoryId);
	//	dishList = dishService.list(dishLambdaQueryWrapper);
	//	return R.success(dishList);
	//}

	@Autowired
	private DishFlavorService dishFlavorService;
	
	@Autowired
	private RedisTemplate redisTemplate;

	@GetMapping("/list")
	public R<List<DishDto>> list(Dish dish){


		// 先尝试从Redis读取列表
		String key ="dish_"+dish.getCategoryId()+"_1";
		Object objectList = redisTemplate.opsForValue().get(key);
		if(objectList != null){
			List<DishDto> dishDtoList = (List<DishDto>)objectList;
			log.info("[菜品列表],从redis读取,{}",dishDtoList);
			return R.success(dishDtoList);
		}

		//构造查询条件
		LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(dish.getCategoryId() != null ,Dish::getCategoryId,dish.getCategoryId());
		//添加条件，查询状态为1（在售状态）的菜品
		queryWrapper.eq(Dish::getStatus,1);
		//添加排序条件
		queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

		List<Dish> list = dishService.list(queryWrapper);

		List<DishDto> dishDtoList = list.stream().map((item) -> {
			DishDto dishDto = new DishDto();
			BeanUtils.copyProperties(item,dishDto);

			Long categoryId = item.getCategoryId();//分类id
			//根据id查询分类对象
			Category category = categoryService.getById(categoryId);
			if(category != null){
				String categoryName = category.getName();
				dishDto.setCategoryName(categoryName);
			}
			//当前菜品的id
			Long dishId = item.getId();
			LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
			lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
			//SQL:select * from dish_flavor where dish_id = ?
			List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
			dishDto.setFlavors(dishFlavorList);

			return dishDto;
		}).collect(Collectors.toList());
		// 存入redis
		redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);
		return R.success(dishDtoList);
	}
}
